﻿#ifndef LINEBUFFER_H
#define LINEBUFFER_H

#include <mutex>
#include <condition_variable>
#include <string.h>
using namespace std;

template <class T>
class LineBuffer
{
public:
    LineBuffer(const unsigned int size): m_size(size)
    {
        m_data = new T[m_size];
        memset(m_data,0x00,m_size*sizeof(T));

        m_useSize = 0;

    }

    ~LineBuffer()
    {
        delete[] m_data;
        m_data = nullptr;
    }

    // 尾部插入数据
    void push_back(T* value,unsigned int count)
    {
        if(count == 0 || value == NULL) return;

        std::unique_lock<mutex> locker(m_mutex);
        m_cv_full.wait(locker,[&](){
            return m_useSize + count < m_size;
        });

        memcpy(m_data + m_useSize,value,count*sizeof(T));
        m_useSize += count;

        m_cv_empty.notify_one();
    }

    // 头部插入数据
    void push_front(T* value,unsigned int count)
    {
        if(count == 0 || value == NULL) return;

        std::lock_guard<mutex> locker(m_mutex);
        m_cv_full.wait(locker,[&](){
            return m_useSize + count < m_size;
        });

        T *tmp = new T[m_size];
        memcpy(tmp,value,count*sizeof(T));
        memcpy(tmp + count,m_data,m_useSize*sizeof(T));
        memcpy(m_data,tmp,(count+m_useSize)*sizeof(T));
        m_useSize += count;
        delete[] tmp;

        m_cv_empty.notify_one();
    }

    // 取出所有数据
    int take_all(T* value)
    {
        std::unique_lock<mutex> locker(m_mutex);

        m_cv_empty.wait(locker,[&](){
            return m_useSize > 0;
        });
        int size = 0;
        memcpy(value,m_data,m_useSize*sizeof(T));
        size = m_useSize;
        m_useSize = 0;

        m_cv_full.notify_one();
        return size;
    }

    // 获取所有数据
    unsigned int data(T *value)
    {
        std::lock_guard<mutex> locker(m_mutex);

        int size = 0;
        memcpy(value,m_data,m_useSize*sizeof(T));
        size = m_useSize;
        return size;
    }

private:
    std::mutex m_mutex;
    std::condition_variable m_cv_full;
    std::condition_variable m_cv_empty;

    const unsigned int m_size;    // 缓存大小
    unsigned int m_useSize; // 使用大小
    T *m_data;  // 数据缓冲区
};

#endif // LINEBUFFER_H
